package com.sunlee.admin.api.module.job.task;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sunlee.admin.api.module.job.dto.UnPackageToPptTaskDTO;
import com.sunlee.admin.api.util.FileUtil;
import com.sunlee.admin.api.util.DecompressUtil;
import com.sunlee.common.core.utils.StringUtil;
import com.sunlee.common.core.constant.Constant;
import com.sunlee.common.core.enums.ErrorCodeEnum;
import com.sunlee.common.core.exception.BusinessException;
import com.sunlee.common.core.utils.DateUtils;
import com.sunlee.common.service.entity.ThirdProductEntity;
import com.sunlee.common.service.enums.ThirdResStatusEnum;
import com.sunlee.common.service.service.ThirdProductService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * 压缩包解压PPT
 *
 * @author sunlee
 */
@Slf4j
@Component("unPackageToPptTask")
public class UnPackageToPptTask implements ITask {

    /**
     * 防止重复执行
     */
    private static boolean isRun = false;

    @Autowired
    private ThirdProductService thirdProductService;

    /**
     * 执行定时任务接口
     *
     * @param params 参数，多参数使用JSON数据
     */
    @Override
    public void run(String params) {
        log.info("unPackageToPptTask定时任务正在执行，参数为：{}", params);

        if (isRun) {
            throw new BusinessException("不可重复执行");
        }

        isRun = true;

        try {
            start(validaDTO(params));
        } finally {
            isRun = false;
            log.info("unPackageToPptTask定时任务执行结束");
        }
    }

    private void start(UnPackageToPptTaskDTO dto) {

        // 查询需解压的zip文件
        List<String> thirdResIds = dto.getThirdResIds();

        List<ThirdProductEntity> list = thirdProductService.list(new LambdaQueryWrapper<ThirdProductEntity>()
                // 指定第三方文件来源
                .eq(ThirdProductEntity::getSource, dto.getSource())
                // 指定第三方资源ID
                .in(CollectionUtils.isNotEmpty(thirdResIds), ThirdProductEntity::getThirdResId, thirdResIds)
                // 只处理状态为"已获取源ZIP"
                .eq(ThirdProductEntity::getStatus, ThirdResStatusEnum.OBTAIN_ZIP.getCode())
                // 限制数量，如果指定第三方资源ID或者未设置则不限制
                .last(CollectionUtils.isEmpty(thirdResIds) && Objects.nonNull(dto.getTotal()), "LIMIT " + dto.getTotal()));

        // 校验查询结果
        if (CollectionUtils.isEmpty(list)) {
            log.warn("找不到需解压的zip文件");
            return;
        }

        // zip解压后的ppt存放目录：默认加上 年月/日 路径
        dto.setTargetFolder(FileUtil.appendSeparator(dto.getTargetFolder()) + FileUtil.appendSeparator(DateUtils.nowDateForYmd()));

        // 校验并创建
        FileUtil.createDirectory(dto.getTargetFolder());

        // 遍历解压
        int cur = 1;
        int total = list.size();
        for (ThirdProductEntity thirdProductEntity : list) {
            log.info("当前解压 [{}/{}] tId={},title={}", cur++, total, thirdProductEntity.getThirdResId(), thirdProductEntity.getTitle());
            unPackageGetPpt(dto, thirdProductEntity);
        }
        // 并发处理
//        list.forEach(thirdProductEntity->unPackageGetPpt(dto, thirdProductEntity));
    }

    public static void main(String[] args) throws Exception {
        try (FileInputStream input = new FileInputStream("C:\\Users\\Administrator.USER-20190429CA\\Desktop\\1.zip");
             ZipInputStream zipInputStream = new ZipInputStream(new BufferedInputStream(input), Charset.forName("GBK"));
        ) {
            ZipEntry ze;
            while ((ze = zipInputStream.getNextEntry()) != null) {
                System.out.println(ze.getName());
            }
        }
    }

    /**
     * 解压压缩包文件到用户指定目录，并更新记录
     */
    private void unPackageGetPpt(UnPackageToPptTaskDTO dto, ThirdProductEntity thirdProductEntity) {
        try {

            // 压缩包路径
            String zipPath = thirdProductEntity.getZipPath();

            // 校验压缩包路径
            if (!FileUtil.isFileExist(zipPath)) {
                throw new BusinessException("解压时找不到压缩包");
            }

            // ppt文件路径（ppt文件存储路径 = 用户指定目录 + 年月 + 日 + 第三方资源ID_资源标题）
            StringBuilder filePathBuilder = new StringBuilder();
            filePathBuilder.append(FileUtil.appendSeparator(dto.getTargetFolder()))
                    .append(thirdProductEntity.getThirdResId())
                    .append(Constant.SYMBOL_UNDERLINE)
                    .append(FileUtil.fileNameCheck(thirdProductEntity.getTitle()));


            // 只解压PPT文件
            boolean isDec = DecompressUtil.decompressUtilWithPpt(zipPath, filePathBuilder);

            if (!isDec) {
                throw new BusinessException("处理失败");
            }

            // 解压成功，更新记录
            thirdProductEntity.setPptPath(filePathBuilder.toString());
            thirdProductEntity.setStatus(ThirdResStatusEnum.OBTAIN_PPT.getCode());
        } catch (Exception e) {
            log.error("解压文件失败：tId={},zipPath={}", thirdProductEntity.getThirdResId(), thirdProductEntity.getZipPath(), e);
            // 解压失败，更新记录
            thirdProductEntity.setStatus(ThirdResStatusEnum.ERROR.getCode());
            thirdProductEntity.setStatusMsg(StringUtil.subString(e.getMessage(), 0, 2000));
        } finally {
            thirdProductService.updateById(thirdProductEntity);
        }
    }


    private UnPackageToPptTaskDTO validaDTO(String params) {
        UnPackageToPptTaskDTO dto = validaParseParam(params, UnPackageToPptTaskDTO.class);
        if (Objects.isNull(dto.getSource()) || dto.getSource() < 0) {
            throw new BusinessException(ErrorCodeEnum.PARAM_NOT_COMPLETE);
        }
        return dto;
    }
}
